package dashboard.classinfo;

import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import com.bj58.ecdata.dao.annotation.Column;
import com.bj58.ecdata.dao.annotation.NotDBColumn;
import com.bj58.ecdata.dao.annotation.Table;
import com.bj58.ecdata.dao.annotation.TableRename;

class ClassInfo
{
    private Map<String,Field> mapAllDBField;
    private Map<String,String> mapDBColumnName;
    private Map<String,Method> mapSetMethod;
    private Map<String,Method> mapGetMethod;
    private Map<String,Field> mapTableRenameField;
    private Map<String,Method> mapTableRenameSetMethod;
    private Map<String,Method> mapTableRenameGetMethod;
    private String tableName;
    
    
    public ClassInfo(Class<?> clazz)
        throws Exception
    {
        setTableName(getTableName(clazz));
        setMapAllDBField(getAllDBFields(clazz));
        setMapDBColumnName(getCloumnName(clazz));
        setMapSetMethod(getSetterMethod(clazz));
        setMapGetMethod(getGetterMethod(clazz));
        setMapTableRenameField(getTableRenameFields(clazz));
        setMapTableRenameGetMethod(getTableRenameGetterMethod(clazz));
        setMapTableRenameSetMethod(getTableRenameSetterMethod(clazz));
    }

    private String getTableName(Class<?> clazz)
    {
        if(clazz.isAnnotationPresent(Table.class))
        {
            Table table = (Table)clazz.getAnnotation(Table.class);
            if(!table.name().equalsIgnoreCase("className"))
                return table.name();
        }
        String name = clazz.getName();
        return name.substring(name.lastIndexOf(".") + 1);
    }

    private Map<String,Field> getAllDBFields(Class<?> clazz)
    {
        Map<String,Field> mapFfields = new HashMap<String,Field>();
        Field fields[] = clazz.getDeclaredFields();
        Field afield[];
        int j = (afield = fields).length;
        for(int i = 0; i < j; i++)
        {
            Field f = afield[i];
            if(!f.isAnnotationPresent(NotDBColumn.class) && !"serialVersionUID".equalsIgnoreCase(f.getName()))
                mapFfields.put(f.getName(), f);
        }

        return mapFfields;
    }

    private Map<String,String> getCloumnName(Class<?> clazz)
    {
        Map<String,String> mapNames = new HashMap<String,String>();
        Collection<Field> fList = mapAllDBField.values();
        for(Iterator<Field> iterator = fList.iterator(); iterator.hasNext();)
        {
            Field f = (Field)iterator.next();
            if(f.isAnnotationPresent(Column.class))
            {
                Column column = (Column)f.getAnnotation(Column.class);
                if(!column.name().equalsIgnoreCase("fieldName"))
                    mapNames.put(f.getName(), column.name());
                else
                    mapNames.put(f.getName(), f.getName());
            } else
            {
                mapNames.put(f.getName(), f.getName());
            }
        }

        return mapNames;
    }

    private Map<String,Method> getSetterMethod(Class<?> clazz)
        throws Exception
    {
        Map<String,Method> mapMethod = new HashMap<String,Method>();
        Collection<Field> fList = mapAllDBField.values();
        PropertyDescriptor lPropDesc[] = Introspector.getBeanInfo(clazz, 1).getPropertyDescriptors();
        for(Iterator<Field> iterator = fList.iterator(); iterator.hasNext();)
        {
            Field f = (Field)iterator.next();
            PropertyDescriptor apropertydescriptor[];
            int j = (apropertydescriptor = lPropDesc).length;
            for(int i = 0; i < j; i++)
            {
                PropertyDescriptor aLPropDesc = apropertydescriptor[i];
                if(!aLPropDesc.getName().equalsIgnoreCase(f.getName()))
                    continue;
                Method setMethod = aLPropDesc.getWriteMethod();
                mapMethod.put(f.getName(), setMethod);
                break;
            }

        }

        for(Iterator<Field> iterator1 = fList.iterator(); iterator1.hasNext();)
        {
            Field f = (Field)iterator1.next();
            Method setterMethod = (Method)mapMethod.get(f.getName());
            if(setterMethod == null)
            {
                String setFunName = "";
                if(f.isAnnotationPresent(Column.class))
                {
                    Column column = (Column)f.getAnnotation(Column.class);
                    if(!column.setFuncName().equalsIgnoreCase("setField"))
                        setFunName = column.setFuncName();
                    else
                        setFunName = (new StringBuilder("set")).append(f.getName().substring(0, 1).toUpperCase()).append(f.getName().substring(1)).toString();
                } else
                {
                    setFunName = (new StringBuilder("set")).append(f.getName().substring(0, 1).toUpperCase()).append(f.getName().substring(1)).toString();
                }
                Method amethod[];
                int l = (amethod = clazz.getMethods()).length;
                for(int k = 0; k < l; k++)
                {
                    Method m = amethod[k];
                    if(!m.getName().equals(setFunName))
                        continue;
                    setterMethod = m;
                    break;
                }

                mapMethod.put(f.getName(), setterMethod);
            }
        }

        for(Iterator<Field> iterator2 = fList.iterator(); iterator2.hasNext();)
        {
            Field f = (Field)iterator2.next();
            Method setterMethod = (Method)mapMethod.get(f.getName());
            if(setterMethod == null)
                throw new Exception((new StringBuilder("can't find set method field:")).append(f.getName()).append("  class:").append(clazz.getName()).toString());
        }

        return mapMethod;
    }

    private Map<String,Method> getGetterMethod(Class<?> clazz)
        throws Exception
    {
        Map<String,Method> mapMethod = new HashMap<String,Method>();
        Collection<Field> fList = mapAllDBField.values();
        PropertyDescriptor lPropDesc[] = Introspector.getBeanInfo(clazz, 1).getPropertyDescriptors();
        for(Iterator<Field> iterator = fList.iterator(); iterator.hasNext();)
        {
            Field f = (Field)iterator.next();
            PropertyDescriptor apropertydescriptor[];
            int j = (apropertydescriptor = lPropDesc).length;
            for(int i = 0; i < j; i++)
            {
                PropertyDescriptor aLPropDesc = apropertydescriptor[i];
                if(!aLPropDesc.getName().equalsIgnoreCase(f.getName()))
                    continue;
                Method getMethod = aLPropDesc.getReadMethod();
                mapMethod.put(f.getName(), getMethod);
                break;
            }

        }

        Field f;
        Method getterMethod;
        for(Iterator<Field> iterator1 = fList.iterator(); iterator1.hasNext(); mapMethod.put(f.getName(), getterMethod))
        {
            f = (Field)iterator1.next();
            getterMethod = (Method)mapMethod.get(f.getName());
            String getFunName = "";
            if(f.isAnnotationPresent(Column.class))
            {
                Column column = (Column)f.getAnnotation(Column.class);
                if(!column.getFuncName().equalsIgnoreCase("getField"))
                    getFunName = column.getFuncName();
                else
                    getFunName = (new StringBuilder("get")).append(f.getName().substring(0, 1).toUpperCase()).append(f.getName().substring(1)).toString();
            } else
            {
                getFunName = (new StringBuilder("get")).append(f.getName().substring(0, 1).toUpperCase()).append(f.getName().substring(1)).toString();
            }
            Method amethod[];
            int l = (amethod = clazz.getMethods()).length;
            for(int k = 0; k < l; k++)
            {
                Method m = amethod[k];
                if(!m.getName().equals(getFunName))
                    continue;
                getterMethod = m;
                break;
            }

        }

        for(Iterator<Field> iterator2 = fList.iterator(); iterator2.hasNext();)
        {
            f = (Field)iterator2.next();
            getterMethod = (Method)mapMethod.get(f.getName());
            if(getterMethod == null)
                throw new Exception((new StringBuilder("can't find get method field:")).append(f.getName()).append("  class:").append(clazz.getName()).toString());
        }

        return mapMethod;
    }

    private Map<String,Field> getTableRenameFields(Class<?> clazz)
    {
        Map<String,Field> mapTableRenamefields = new HashMap<String,Field>();
        Field fields[] = clazz.getDeclaredFields();
        Field afield[];
        int j = (afield = fields).length;
        for(int i = 0; i < j; i++)
        {
            Field f = afield[i];
            if(f.isAnnotationPresent(TableRename.class))
                mapTableRenamefields.put(f.getName(), f);
        }

        return mapTableRenamefields;
    }

    private Map<String,Method> getTableRenameSetterMethod(Class<?> clazz)
        throws Exception
    {
        Map<String,Method> mapMethod = new HashMap<String,Method>();
        Collection<Field> fList = mapTableRenameField.values();
        PropertyDescriptor lPropDesc[] = Introspector.getBeanInfo(clazz, 1).getPropertyDescriptors();
        for(Iterator<Field> iterator = fList.iterator(); iterator.hasNext();)
        {
            Field f = (Field)iterator.next();
            PropertyDescriptor apropertydescriptor[];
            int j = (apropertydescriptor = lPropDesc).length;
            for(int i = 0; i < j; i++)
            {
                PropertyDescriptor aLPropDesc = apropertydescriptor[i];
                if(!aLPropDesc.getName().equalsIgnoreCase(f.getName()))
                    continue;
                Method setMethod = aLPropDesc.getWriteMethod();
                mapMethod.put(f.getName(), setMethod);
                break;
            }

        }

        for(Iterator<Field> iterator1 = fList.iterator(); iterator1.hasNext();)
        {
            Field f = (Field)iterator1.next();
            Method setterMethod = (Method)mapMethod.get(f.getName());
            if(setterMethod == null)
            {
                String setFunName = "";
                if(f.isAnnotationPresent(Column.class))
                {
                    Column column = (Column)f.getAnnotation(Column.class);
                    if(!column.setFuncName().equalsIgnoreCase("setField"))
                        setFunName = column.setFuncName();
                    else
                        setFunName = (new StringBuilder("set")).append(f.getName().substring(0, 1).toUpperCase()).append(f.getName().substring(1)).toString();
                } else
                {
                    setFunName = (new StringBuilder("set")).append(f.getName().substring(0, 1).toUpperCase()).append(f.getName().substring(1)).toString();
                }
                Method amethod[];
                int l = (amethod = clazz.getMethods()).length;
                for(int k = 0; k < l; k++)
                {
                    Method m = amethod[k];
                    if(!m.getName().equals(setFunName))
                        continue;
                    setterMethod = m;
                    break;
                }

                mapMethod.put(f.getName(), setterMethod);
            }
        }

        for(Iterator<Field> iterator2 = fList.iterator(); iterator2.hasNext();)
        {
            Field f = (Field)iterator2.next();
            Method setterMethod = (Method)mapMethod.get(f.getName());
            if(setterMethod == null)
                throw new Exception((new StringBuilder("can't find set method field:")).append(f.getName()).append("  class:").append(clazz.getName()).toString());
        }

        return mapMethod;
    }

    private Map<String,Method> getTableRenameGetterMethod(Class<?> clazz)
        throws Exception
    {
        Map<String,Method> mapMethod = new HashMap<String,Method>();
        Collection<Field> fList = mapTableRenameField.values();
        PropertyDescriptor lPropDesc[] = Introspector.getBeanInfo(clazz, 1).getPropertyDescriptors();
        for(Iterator<Field> iterator = fList.iterator(); iterator.hasNext();)
        {
            Field f = (Field)iterator.next();
            PropertyDescriptor apropertydescriptor[];
            int j = (apropertydescriptor = lPropDesc).length;
            for(int i = 0; i < j; i++)
            {
                PropertyDescriptor aLPropDesc = apropertydescriptor[i];
                if(!aLPropDesc.getName().equalsIgnoreCase(f.getName()))
                    continue;
                Method getMethod = aLPropDesc.getReadMethod();
                mapMethod.put(f.getName(), getMethod);
                break;
            }

        }

        Field f;
        Method getterMethod;
        for(Iterator<Field> iterator1 = fList.iterator(); iterator1.hasNext(); mapMethod.put(f.getName(), getterMethod))
        {
            f = (Field)iterator1.next();
            getterMethod = (Method)mapMethod.get(f.getName());
            String getFunName = "";
            if(f.isAnnotationPresent(Column.class))
            {
                Column column = (Column)f.getAnnotation(Column.class);
                if(!column.getFuncName().equalsIgnoreCase("getField"))
                    getFunName = column.getFuncName();
                else
                    getFunName = (new StringBuilder("get")).append(f.getName().substring(0, 1).toUpperCase()).append(f.getName().substring(1)).toString();
            } else
            {
                getFunName = (new StringBuilder("get")).append(f.getName().substring(0, 1).toUpperCase()).append(f.getName().substring(1)).toString();
            }
            Method amethod[];
            int l = (amethod = clazz.getMethods()).length;
            for(int k = 0; k < l; k++)
            {
                Method m = amethod[k];
                if(!m.getName().equals(getFunName))
                    continue;
                getterMethod = m;
                break;
            }

        }

        for(Iterator<Field> iterator2 = fList.iterator(); iterator2.hasNext();)
        {
            f = (Field)iterator2.next();
            getterMethod = (Method)mapMethod.get(f.getName());
            if(getterMethod == null)
                throw new Exception((new StringBuilder("can't find get method field:")).append(f.getName()).append("  class:").append(clazz.getName()).toString());
        }

        return mapMethod;
    }

    public Map<String,Field> getMapAllDBField()
    {
        return mapAllDBField;
    }

    public void setMapAllDBField(Map<String,Field> mapAllDBField)
    {
        this.mapAllDBField = mapAllDBField;
    }

    public Map<String,String> getMapDBColumnName()
    {
        return mapDBColumnName;
    }

    public void setMapDBColumnName(Map<String,String> mapDBColumnName)
    {
        this.mapDBColumnName = mapDBColumnName;
    }

    public Map<String,Method> getMapSetMethod()
    {
        return mapSetMethod;
    }

    public void setMapSetMethod(Map<String,Method> mapSetMethod)
    {
        this.mapSetMethod = mapSetMethod;
    }

    public Map<String,Method> getMapGetMethod()
    {
        return mapGetMethod;
    }

    public void setMapGetMethod(Map<String,Method> mapGetMethod)
    {
        this.mapGetMethod = mapGetMethod;
    }

    public String getTableName()
    {
        return tableName;
    }

    public void setTableName(String tableName)
    {
        this.tableName = tableName;
    }

    public Map<String,Field> getMapTableRenameField()
    {
        return mapTableRenameField;
    }

    public void setMapTableRenameField(Map<String,Field> mapTableRenameField)
    {
        this.mapTableRenameField = mapTableRenameField;
    }

    public Map<String,Method> getMapTableRenameSetMethod()
    {
        return mapTableRenameSetMethod;
    }

    public void setMapTableRenameSetMethod(Map<String,Method> mapTableRenameSetMethod)
    {
        this.mapTableRenameSetMethod = mapTableRenameSetMethod;
    }

    public Map<String,Method> getMapTableRenameGetMethod()
    {
        return mapTableRenameGetMethod;
    }

    public void setMapTableRenameGetMethod(Map<String,Method> mapTableRenameGetMethod)
    {
        this.mapTableRenameGetMethod = mapTableRenameGetMethod;
    }

}
